import { Context, Next } from 'koa';
import { errorLogger } from '../config/logger';
import { envConfig } from '../config/environment';
import { HttpError } from '../exceptions/HttpError';
import { generateErrorResponse } from '../utils';
export interface AppError extends Error {
  status?: number;
  details?: any;
}

export const errorHandler = async (ctx: Context, next: Next) => {
  try {
    await next();
  } catch (error: any) {
    // 记录错误日志
    errorLogger(error, ctx);

    // 如果是 HttpError，直接使用其状态码和消息
    if (error instanceof HttpError) {
      ctx.status = error.statusCode;
      ctx.body = error.toJSON();
      return;
    }

    // Mongoose 验证错误
    if (error.name === 'ValidationError') {
      const errors = Object.values(error.errors).map((err: any) => ({
        field: err.path,
        message: err.message
      }));

      // ctx.status = 422;
      // ctx.body = {
      //   error: 'ValidationError',
      //   message: '数据验证失败',
      //   statusCode: 422,
      //   details: errors,
      //   timestamp: dayjs().format('YYYY年MM月DD日 HH:mm:ss')
      // };
      generateErrorResponse(ctx, '数据验证失败', 422, errors);
      return;
    }

    // MongoDB 重复键错误
    if (error.code === 11000) {
      const field = Object.keys(error.keyValue)[0];

      generateErrorResponse(ctx, `${field} 已存在`, 409, error.details);
      return;
    }

    // CastError (无效的 ObjectId)
    if (error.name === 'CastError') {

      generateErrorResponse(ctx, '无效的ID格式', 400, error.details);
      return;
    }

    // 处理现有的 AppError
    if (error.status) {
      generateErrorResponse(ctx, error.message, error.status, error.details);
      return;
    }
    generateErrorResponse(ctx, envConfig.nodeEnv === 'production' ? '服务器内部错误' : error.message, 500);
  }
};

export const createError = (message: string, status: number = 500, details?: any): AppError => {
  const error: AppError = new Error(message);
  error.status = status;
  error.details = details?.details || details?.message || details;
  return error;
};

// 向后兼容的快捷方法
export { HttpError };